home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / UUPC11QS.ARJ / ULIB.C < prev    next >
C/C++ Source or Header  |  1991-12-07  |  12KB  |  367 lines

  1. /*
  2.    ibmpc/ulib.c
  3.  
  4.    DCP system-dependent library
  5.  
  6.    Services provided by ulib.c:
  7.  
  8.    - login
  9.    - UNIX commands simulation
  10.    - serial I/O
  11.    - rnews
  12.  
  13.    Updated:
  14.  
  15.       14May89  - Added hangup() procedure                               ahd
  16.       21Jan90  - Replaced code for rnews() from Wolfgang Tremmel
  17.                  <tremmel@garf.ira.uka.de> to correct failure to
  18.                  properly read compressed news.                         ahd
  19.    6  Sep 90   - Change logging of line data to printable               ahd
  20.       8 Sep 90 - Split ulib.c into dcplib.c and ulib.c                  ahd
  21. */
  22.  
  23. #include <fcntl.h>
  24. #include <io.h>
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27. #include <string.h>
  28. #include <time.h>
  29.  
  30. #include "lib.h"
  31. #include "ulib.h"
  32. #include "comm.h"
  33. #include "ssleep.h"
  34.  
  35. boolean   port_active = FALSE;  /* TRUE = port handler handler active  */
  36.  
  37. static BPS current_baud;
  38. static char current_direct;
  39. static int old_status = 0x00;
  40.  
  41. currentfile();
  42.  
  43. /* IBM-PC I/O routines */
  44.  
  45. /* "DCP" a uucp clone. Copyright Richard H. Lamb 1985,1986,1987 */
  46.  
  47. /*************** BASIC I/O ***************************/
  48. /* Saltzers serial package (aka Info-IBMPC COM_PKG2):
  49.  * Some notes:  When packets are flying in both directions, there seems to
  50.  * be some interrupt handling problems as far as receiving.  Checksum errors
  51.  * may therefore occur often even though we recover from them.  This is
  52.  * especially true with sliding windows.  Errors are very few in the VMS
  53.  * version.  RH Lamb
  54.  */
  55.  
  56.  
  57. #define  STOPBIT  1
  58. #define LINELOG "LineData.Log"      /* log serial line data here */
  59.  
  60. static int log_handle;
  61. static int logmode = 0;             /* Not yet logging            */
  62. #define WRITING 1
  63. #define READING 2
  64. static FILE *log_stream;
  65. static boolean hangup_needed = TRUE;
  66.  
  67. /*--------------------------------------------------------------------*/
  68. /*    o p e n l i n e                                                 */
  69. /*                                                                    */
  70. /*    Open the serial port for I/O                                    */
  71. /*--------------------------------------------------------------------*/
  72.  
  73. int openline(char *name, BPS baud, const boolean direct)
  74. {
  75.    int   value;
  76.  
  77.    if (port_active)              /* Was the port already active?     ahd   */
  78.       closeline();               /* Yes --> Shutdown it before open  ahd   */
  79.  
  80.    printmsg(15, "openline: %s, %d", name, baud);
  81.  
  82.    logmode = 0;
  83.  
  84.    current_direct = direct ? 'D' : 'M' ;
  85.  
  86.    if (sscanf(name, "COM%d", &value) != 1)
  87.    {
  88.       printmsg(0,"Communications port must be format COMx, was %s",
  89.                 name);
  90.       panic();
  91.    }
  92.  
  93.    select_port(value);
  94.    save_com();
  95.    install_com();
  96.    open_com(baud, current_direct, 'N', STOPBIT, 'D');
  97.    current_baud = baud;
  98.    dtr_on();
  99.  
  100.    /* log serial line data only if log file already exists */
  101.    log_handle = open(LINELOG, O_WRONLY | O_TRUNC | O_BINARY);
  102.    if (log_handle != -1) {
  103.       printmsg(15, "openline: logging serial line data to %s", LINELOG);
  104.       log_stream = fdopen(log_handle, "wb");
  105.    }
  106.  
  107.    port_active = TRUE;     /* record status for error handler */
  108.  
  109.    return 0;
  110.  
  111. } /*openline*/
  112.  
  113.  
  114. /*--------------------------------------------------------------------*/
  115. /*    s r e a d                                                       */
  116. /*                                                                    */
  117. /*    Read from the serial port                                       */
  118. /*                                                                    */
  119. /*    Non-blocking read essential to "g" protocol.  See               */
  120. /*    "dcpgpkt.c" for description.  This all changes in a             */
  121. /*    multi-tasking system.  Requests for I/O should get queued       */
  122. /*    and an event flag given.  Then the requesting process (e.g.     */
  123. /*    gmachine()) waits for the event flag to fire processing         */
  124. /*    either a read or a write.  Could be implemented on VAX/VMS      */
  125. /*    or DG but not MS-DOS.                                           */
  126. /*--------------------------------------------------------------------*/
  127.  
  128. unsigned int sread(char *buffer, unsigned int wanted, unsigned int timeout)
  129. {
  130.    time_t start;
  131.  
  132.    hangup_needed = TRUE;
  133.  
  134.    start = time(nil(time_t));
  135.  
  136.    for ( ; ; )
  137.    {
  138.       unsigned int pending;
  139.       pending = r_count_pending();
  140.       printmsg(20, "sread: pending=%d, wanted=%d", pending, wanted);
  141.       if ( debuglevel >= 4 )
  142.       {
  143.          int status = modem_status();
  144.  
  145.          if ( status != old_status )
  146.          {
  147.             old_status = status;
  148.             printmsg(4,"sread: Modem status changed to %#02x", status);
  149.          } /* if ( status != old_status ) */
  150.  
  151.       } /* if ( debuglevel >= 4 ) */
  152.  
  153.       if (pending >= wanted) {   /* got enough in the buffer? */
  154.          unsigned int i;
  155.          for (i = 0; i < wanted; i++)
  156.             *buffer++ = (char) receive_com();
  157.          if (log_handle != -1) {
  158. #ifdef VERBOSE
  159.             char s[18];
  160. #endif
  161.             buffer -= wanted;
  162.             if (logmode != READING)
  163.             {
  164.                fputs("\nRead:  ", log_stream);
  165.                logmode = READING;
  166.             } /* if */
  167. #ifdef VERBOSE
  168.             for (i = 0; i < wanted; i++) {
  169.                itoa(0x100 | (unsigned) *buffer++, s, 16);
  170.                                              /* Make it printable hex */
  171.                fwrite(s, 1, 2, log_stream);  /* Write hex to the log    */
  172.             } /* for */
  173. #else
  174.             fwrite(buffer, 1, wanted, log_stream);
  175.                                              /* Write data to the log */
  176. #endif
  177.          } /* if */
  178.  
  179.          return pending;
  180.       } else {
  181.          time_t   now     = time(nil(time_t));
  182.          time_t   elapsed = now - start;
  183.  
  184.          if (elapsed >= (long) timeout)
  185.             return pending;
  186.  
  187.          ddelay(0);                    /* Surrender our time slice   */
  188.  
  189.       } /* else */
  190.    } /* for ( ; ; ) */
  191.  
  192. } /*sread*/
  193.  
  194. /*--------------------------------------------------------------------*/
  195. /*    s w r i t e                                                     */
  196. /*                                                                    */
  197. /*    Write to the serial port                                        */
  198. /*--------------------------------------------------------------------*/
  199.  
  200. int swrite(char *data, unsigned int len)
  201. {
  202.    unsigned int i;
  203.  
  204.    hangup_needed = TRUE;
  205.    for (i = 0; i < len; i++)
  206.    {
  207.       if ( debuglevel >= 4 )
  208.       {
  209.          int status = modem_status();
  210.  
  211.          if ( status != old_status )
  212.          {
  213.             old_status = status;
  214.             printmsg(4,"swrite: Modem status changed to %#02x", status);
  215.          } /* if ( status != old_status ) */
  216.  
  217.       } /* if ( debuglevel >= 4 ) */
  218.       send_com(*data++);
  219.    }
  220.  
  221.    if (log_handle != -1) {
  222. #ifdef VERBOSE
  223.       char s[18];
  224. #endif
  225.       if (logmode != WRITING)
  226.       {
  227.          fputs("\nWrite: ", log_stream);
  228.          logmode = WRITING;
  229.       } /* if */
  230.       data -= len;
  231. #ifdef VERBOSE
  232.       for (i = 0; i < len; i++) {
  233.          itoa(0x100 | (unsigned) *data++, s, 16);
  234.                                         /* Make it printable hex  ahd */
  235.          fwrite(s, 1, 2, log_stream);
  236.       } /* for */
  237. #else
  238.       fwrite(data, 1, len, log_stream);   /* Write data to the log */
  239. #endif
  240.    } /* if */
  241.  
  242.    return len;
  243.  
  244. } /*swrite*/
  245.  
  246.  
  247. /*--------------------------------------------------------------------*/
  248. /*    s s e n d b r k                                                 */
  249. /*                                                                    */
  250. /*    Send a break signal out the serial port                         */
  251. /*--------------------------------------------------------------------*/
  252.  
  253. void ssendbrk(unsigned int duration)
  254. {
  255.  
  256.    printmsg(12, "ssendbrk: %d", duration);
  257.  
  258.    break_com();
  259.  
  260. } /*ssendbrk*/
  261.  
  262.  
  263. /*--------------------------------------------------------------------*/
  264. /*    c l o s e l i n e                                               */
  265. /*                                                                    */
  266. /*    Close the serial port down                                      */
  267. /*--------------------------------------------------------------------*/
  268.  
  269. void closeline(void)
  270. {
  271.    int far *stats;
  272.  
  273.    if (!port_active)
  274.       panic();
  275.  
  276.    port_active = FALSE; /* flag port closed for error handler  */
  277.  
  278.    dtr_off();
  279.    close_com();
  280.    restore_com();
  281.  
  282.    if (log_handle != -1) {    /* close serial line log file */
  283.       fclose(log_stream);
  284.       close(log_handle);
  285.    };
  286.  
  287.    stats = com_errors();
  288.    printmsg(3, "Buffer overflows: %-4d",stats[COM_EOVFLOW]);
  289.    printmsg(3, "Receive overruns: %-4d", stats[COM_EOVRUN]);
  290.    printmsg(3, "Break characters: %-4d", stats[COM_EBREAK]);
  291.    printmsg(3, "Framing errors:   %-4d", stats[COM_EFRAME]);
  292.    printmsg(3, "Parity errors:    %-4d", stats[COM_EPARITY]);
  293.    printmsg(3, "Transmit errors:  %-4d", stats[COM_EXMIT]);
  294.    printmsg(3, "DSR errors:       %-4d", stats[COM_EDSR]);
  295.    printmsg(3, "CTS errors:       %-4d", stats[COM_ECTS]);
  296.  
  297. } /*closeline*/
  298.  
  299.  
  300. /*--------------------------------------------------------------------*/
  301. /*    H a n g u p                                                     */
  302. /*                                                                    */
  303. /*    Hangup the telephone by dropping DTR.  Works with HAYES and     */
  304. /*    many compatibles.                                               */
  305. /*    14 May 89 Drew Derbyshire                                       */
  306. /*--------------------------------------------------------------------*/
  307.  
  308. void hangup( void )
  309. {
  310.       if (!hangup_needed)
  311.          return;
  312.       hangup_needed = FALSE;
  313.       dtr_off();              /* Hang the phone up                         */
  314.       printmsg(3,"hangup: Dropped DTR");
  315.       ddelay(500);            /* Really only need 250 milliseconds         */
  316.       dtr_on();               /* Bring the modem back on-line              */
  317.       ddelay(500);            /* Now wait for the poor thing to recover    */
  318.  
  319. } /* hangup */
  320.  
  321. /*--------------------------------------------------------------------*/
  322. /*    S I O S p e e d                                                 */
  323. /*                                                                    */
  324. /*    Re-specify the speed of an opened serial port                   */
  325. /*                                                                    */
  326. /*    Dropped the DTR off/on calls because this makes a Hayes drop    */
  327. /*    the line if configured properly, and we don't want the modem    */
  328. /*    to drop the phone on the floor if we are performing             */
  329. /*    autobaud.                                                       */
  330. /*                                                                    */
  331. /*    (Configured properly = standard method of making a Hayes        */
  332. /*    hang up the telephone, especially when you can't get it into    */
  333. /*    command state because it is at the wrong speed or whatever.)    */
  334. /*--------------------------------------------------------------------*/
  335.  
  336. void SIOSpeed(BPS baud)
  337. {
  338.  
  339.    close_com();
  340.    open_com(baud, current_direct , 'N', STOPBIT, 'D');
  341.    current_baud = baud;
  342.  
  343. } /*SIOSpeed*/
  344.  
  345. /*--------------------------------------------------------------------*/
  346. /*    f l o w c o n t r o l                                           */
  347. /*                                                                    */
  348. /*    Enable/Disable in band (XON/XOFF) flow control                  */
  349. /*--------------------------------------------------------------------*/
  350.  
  351. void flowcontrol( boolean flow )
  352. {
  353.    close_com();
  354.    open_com(current_baud, current_direct, 'N', STOPBIT, flow ? 'E' : 'D');
  355. } /*flowcontrol*/
  356.  
  357. /*--------------------------------------------------------------------*/
  358. /*    G e t S p e e d                                                 */
  359. /*                                                                    */
  360. /*    Report current speed of communications connection               */
  361. /*--------------------------------------------------------------------*/
  362.  
  363. BPS GetSpeed( void )
  364. {
  365.    return current_baud;
  366. } /* GetSpeed */
  367.